﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing;
using System.Web.Mvc;
using System.Text.RegularExpressions;
using CMN.Common;
namespace CMN.Controllers.Mvc.Routing
{
    public class DomainRoute : Route
    {
        private Regex domainRegex;
        private Regex pathRegex;

        public string Domain { get; set; }

        public DomainRoute(string domain, string url, RouteValueDictionary defaults)
            : base(url, defaults, new MvcRouteHandler())
        {
            Domain = domain;
        }

        public DomainRoute(string domain, string url, RouteValueDictionary defaults, IRouteHandler routeHandler)
            : base(url, defaults, routeHandler)
        {
            Domain = domain;
        }

        public DomainRoute(string domain, string url, object defaults)
            : base(url, new RouteValueDictionary(defaults), new MvcRouteHandler())
        {
            Domain = domain;
        }

        public DomainRoute(string domain, string url, object defaults, IRouteHandler routeHandler)
            : base(url, new RouteValueDictionary(defaults), routeHandler)
        {
            Domain = domain;
        }

        public DomainRoute(string domain, string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler)
            : base(url, defaults,constraints,dataTokens, routeHandler)
        {
          
            Domain = domain;
        }

        public override RouteData GetRouteData(HttpContextBase httpContext)
        {
            //AppLog.Write("Domain:" + Domain,AppLog.LogMessageType.Debug);
            // 构造 regex
            domainRegex = CreateRegex(Domain);
            string strUrl = Url;
            //AppLog.Write("Url:" + Url, AppLog.LogMessageType.Debug);
            strUrl = CreateRegex2(strUrl);
            //strUrl = strUrl.Replace("/", @"\/?");
            //strUrl = strUrl.Replace(".", @"\.?");
            //strUrl = strUrl.Replace("-", @"\-?");
            //strUrl = strUrl.Replace("{", @"(?<");
            foreach (string strTemp in Constraints.Keys)
            {
                if (!string.IsNullOrEmpty(Constraints[strTemp].ToString()))
                {
                  
                    strUrl = strUrl.Replace(string.Concat(strTemp, "}"), string.Concat(strTemp, @">(", Constraints[strTemp].ToString(), "))"));
                    //AppLog.Write("CreateRegex:"+source, AppLog.LogMessageType.Debug);
                }
            }
            strUrl = strUrl.Replace("}", @">([a-zA-Z0-9_\.]*))");
            //Url= CreateRegex2(Url);
            //AppLog.Write("Url:" + strUrl, AppLog.LogMessageType.Debug);
            pathRegex = new Regex("^" + strUrl + "$");
           
         
            //AppLog.Write( Utils.GetIP()+"GetRouteData"+Domain, AppLog.LogMessageType.Debug);
            // 请求信息
            string requestDomain = httpContext.Request.Headers["host"];
            if (!string.IsNullOrEmpty(requestDomain))
            {
                if (requestDomain.IndexOf(":") > 0)
                {
                    requestDomain = requestDomain.Substring(0, requestDomain.IndexOf(":"));
                }
            }
            else
            {
                requestDomain = httpContext.Request.Url.Host;
            }
            string requestPath = string.Concat(httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2), httpContext.Request.PathInfo);

            // 匹配域名和路由
            Match domainMatch = domainRegex.Match(requestDomain);
            Match pathMatch = pathRegex.Match(requestPath);
            //AppLog.Write(requestDomain + ":requestDomain", AppLog.LogMessageType.Debug);
            //AppLog.Write(requestPath + ":requestPath", AppLog.LogMessageType.Debug);
            // 路由数据
            RouteData data = null;
            //AppLog.Write("domainMatch.Success" + domainMatch.Success + " --pathMatch.Success" + pathMatch.Success, AppLog.LogMessageType.Debug);
            if (domainMatch.Success && pathMatch.Success)
            {
                data = new RouteData(this, RouteHandler);

                // 添加默认选项
                if (Defaults != null)
                {
                    foreach (KeyValuePair<string, object> item in Defaults)
                    {
                        data.Values[item.Key] = item.Value;
                       // AppLog.Write(item.Key +item.Value+ "GetRouteData" + Domain, AppLog.LogMessageType.Debug);
                    }
                }

                // 匹配域名路径
               // Regex reg = null;
                for (int i = 1; i < pathMatch.Groups.Count; i++)
                {
                   
                    Group group = pathMatch.Groups[i];
                    if (group.Success)
                    {
                        string key = pathRegex.GroupNameFromNumber(i);
                       // AppLog.Write("i::"+i.ToString()+"___key:::" + key + "______ group.Value:::" + group.Value, AppLog.LogMessageType.Debug);
                        if (!string.IsNullOrEmpty(key) && !char.IsNumber(key, 0))
                        {
                            if (!string.IsNullOrEmpty(group.Value))
                            {
                                //foreach (string str in this.Constraints.Keys)
                                //{
                                //    AppLog.Write("this.Constraints:----" + str + this.Constraints[str].ToString(), AppLog.LogMessageType.Debug);
                                //}
                                //AppLog.Write("pathMatch-group.Value【" + key +":::"+ group.Value + this.Constraints.Count.ToString(), AppLog.LogMessageType.Debug);
                                //if (this.Constraints.ContainsKey(key))
                                //{
                                //    //AppLog.Write("key::::" + key + "___this.Constraints[key].ToString()" + this.Constraints[key].ToString() + "____group.Value:::" + group.Value, AppLog.LogMessageType.Debug);
                                //    reg = new Regex(this.Constraints[key].ToString());
                                //    if (!reg.IsMatch(group.Value))
                                //    {
                                //        return  null;
                                //    }
                                //    //else
                                //    //{
                                //    //    data.Values[key] = group.Value;
                                //    //}

                                //}
                                //else
                                //{
                                //    data.Values[key] = group.Value;
                                //}
                                data.Values[key] = group.Value;

                            }
                        }
                    }
                }

                //AppLog.Write("domainMatch.Groups.Count" + domainMatch.Groups.Count, AppLog.LogMessageType.Debug);
                // 匹配域名路由
                for (int i = 1; i < domainMatch.Groups.Count; i++)
                {
                    Group group = domainMatch.Groups[i];
                    if (group.Success)
                    {
                        string key = domainRegex.GroupNameFromNumber(i);

                        if (!string.IsNullOrEmpty(key) && !char.IsNumber(key, 0))
                        {
                            if (!string.IsNullOrEmpty(group.Value))
                            {
                                data.Values[key] = group.Value;
                              //  AppLog.Write(key+"domainMatch-group.Value" + group.Value, AppLog.LogMessageType.Debug);
                            }
                        }
                    }
                }

               // AppLog.Write("domainMatch.end----------------------" , AppLog.LogMessageType.Debug);
            }
          
            return data;
        }

        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            return base.GetVirtualPath(requestContext, RemoveDomainTokens(values));
        }

        public DomainData GetDomainData(RequestContext requestContext, RouteValueDictionary values)
        {
            // 获得主机名
            string hostname = Domain;
            foreach (KeyValuePair<string, object> pair in values)
            {
                hostname = hostname.Replace("{" + pair.Key + "}", pair.Value.ToString());
            }

            // Return 域名数据
            return new DomainData
            {
                Protocol = "http",
                HostName = hostname,
                Fragment = ""
            };
        }

        private Regex CreateRegex(string source)
        {
            // 替换
            source = source.Replace("/", @"\/?");
            source = source.Replace(".", @"\.?");
            source = source.Replace("-", @"\-?");
            source = source.Replace("{", @"(?<");
            source = source.Replace("}", @">([a-zA-Z0-9_\.]*))");
            //AppLog.Write("CreateRegex:"+source, AppLog.LogMessageType.Debug);
            
            return new Regex("^" + source + "$");
        }
        private string CreateRegex2(string source)
        {
            // 替换
            source = source.Replace("/", @"\/?");
            source = source.Replace(".", @"\.?");
            source = source.Replace("-", @"\-?");
            source = source.Replace("{", @"(?<");
            //source = source.Replace("}", @">([a-zA-Z0-9_\.]*))");
            //   AppLog.Write("CreateRegex:"+source, AppLog.LogMessageType.Debug);
            return source;
         

         
        }

        private RouteValueDictionary RemoveDomainTokens(RouteValueDictionary values)
        {
            Regex tokenRegex = new Regex(@"({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?");
            Match tokenMatch = tokenRegex.Match(Domain);
            for (int i = 0; i < tokenMatch.Groups.Count; i++)
            {
                Group group = tokenMatch.Groups[i];
                if (group.Success)
                {
                    string key = group.Value.Replace("{", "").Replace("}", "");
                    if (values.ContainsKey(key))
                        values.Remove(key);
                }
            }

            return values;
        }
    }
}
